using System.ComponentModel;
using System.Drawing;

namespace System.Windows.Forms.ColorControls
{
    /// <summary>
    /// Summary description for ColorList.
    /// </summary>
    public class ColorList : System.Windows.Forms.ListBox
    {
        private const int clrBoxPadding = 2;
        private const int clrBoxWidth = 20;
        private const int defaultItemHeight = 14;

        private ColorSet colorSet = ColorSet.Custom;

        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        /// <summary>
        /// Default constructor
        /// </summary>
        public ColorList()
        {
            // This call is required by the Windows.Forms Form Designer.
            InitializeComponent();

            this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
            this.ItemHeight = defaultItemHeight;
        }

        /// <summary>
        /// Set/get the set of colors displayed by the control.<br></br><br></br>
        /// See <see cref="ColorSet">ColorSet</see>.
        /// </summary>
        [Browsable(true)]
        [Category("ColorList")]
        [DefaultValue(ColorSet.Custom)]
        [Description("Get/set the palette of colors to be displayed.")]
        public ColorSet ColorSet
        {
            get
            {
                return colorSet;
            }
            set
            {
                if (value != colorSet)
                {
                    colorSet = value;
                    if (value == ColorSet.Web)
                    {
                        Items.Clear();
                        foreach (KnownColor kc in Enum.GetValues(typeof(KnownColor)))
                        {
                            if ((int)kc >= 27)
                                Items.Add(Color.FromKnownColor(kc));
                        }
                    }
                    else if (value == ColorSet.System)
                    {
                        Items.Clear();
                        foreach (KnownColor kc in Enum.GetValues(typeof(KnownColor)))
                        {
                            if ((int)kc < 27)
                                Items.Add(Color.FromKnownColor(kc));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Overrides drawing mode for the combobox items
        /// </summary>
        [Browsable(false),
        DefaultValue(DrawMode.OwnerDrawFixed)]
        public override System.Windows.Forms.DrawMode DrawMode
        {
            get { return base.DrawMode; }
            set { base.DrawMode = value; }
        }

        /// <summary>
        /// Overrides the item height
        /// </summary>
        [DefaultValue(defaultItemHeight)]
        public override int ItemHeight
        {
            get { return base.ItemHeight; }
            set { base.ItemHeight = value; }
        }

        public new System.Windows.Forms.ListBox.ObjectCollection Items
        {
            get { return base.Items; }
        }

        public bool ShouldSerializeItems()
        {
            return (colorSet == ColorSet.Custom);
        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        /// <summary>
        /// Draws current color item
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
        {
            if (e.Index < Items.Count)
            {
                bool selected = (e.State & DrawItemState.Selected) > 0;
                bool editSel = (e.State & DrawItemState.ComboBoxEdit ) > 0;
                Color clr;
                if (Items[e.Index] is Color)
                    clr = (Color)Items[e.Index];
                else if (Items[e.Index] is string)
                    clr = Color.FromName((string)Items[e.Index]);
                else
                    throw new ArgumentException("ColorList item must be a System.Color or String");
                e.Graphics.FillRectangle((selected && !editSel) ? SystemBrushes.Highlight : SystemBrushes.Window, e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
                e.Graphics.FillRectangle(new SolidBrush(clr), e.Bounds.Left+clrBoxPadding, e.Bounds.Top+clrBoxPadding, clrBoxWidth, e.Bounds.Height-(clrBoxPadding*2));
                e.Graphics.DrawRectangle(SystemPens.WindowText, new Rectangle(e.Bounds.Left+1, e.Bounds.Top+1, 21, e.Bounds.Height-3));
                string clrName = (clr.IsNamedColor) ? clr.Name : String.Format("{0}, {1}, {2}", clr.R, clr.G, clr.B);
                e.Graphics.DrawString(clrName, Font, selected ? SystemBrushes.HighlightText : SystemBrushes.WindowText, new Point(e.Bounds.Left + (clrBoxPadding*3) + clrBoxWidth, e.Bounds.Top));
            }
        }

        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }
    }
}